// Copyright Epic Games, Inc. All Rights Reserved. // 版权声明，Epic Games 公司保留所有权利

#pragma once // 头文件保护，确保头文件只被编译一次

#include "GameplayCueManager.h" // 包含 GameplayCueManager 的头文件，继承自该类

#include "LyraGameplayCueManager.generated.h" // 包含自动生成的 UCLASS 等宏所需的头文件

class FString; // 前向声明 FString 类
class UClass; // 前向声明 UClass 类
class UObject; // 前向声明 UObject 类
class UWorld; // 前向声明 UWorld 类
struct FObjectKey; // 前向声明 FObjectKey 结构体

/**
 * ULyraGameplayCueManager
 *
 * Game-specific manager for gameplay cues
 * 游戏特定的 GameplayCue 管理器
 */
UCLASS() // UCLASS 宏，声明这是一个 UObject 类，由 Unreal Header Tool (UHT) 处理
class ULyraGameplayCueManager : public UGameplayCueManager // 定义 ULyraGameplayCueManager 类，继承自 UGameplayCueManager
{
	GENERATED_BODY() // GENERATED_BODY 宏，由 UHT 生成，包含必要的类型声明和反射代码

public:
	ULyraGameplayCueManager(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); // 构造函数，接受一个 FObjectInitializer 引用，默认为 FObjectInitializer::Get()

	static ULyraGameplayCueManager* Get(); // 静态成员函数，用于获取 ULyraGameplayCueManager 单例实例

	//~UGameplayCueManager interface // 注释，表示开始重写 UGameplayCueManager 接口
	virtual void OnCreated() override; // 重写 OnCreated 函数，在 GameplayCueManager 创建后调用
	virtual bool ShouldAsyncLoadRuntimeObjectLibraries() const override; // 重写 ShouldAsyncLoadRuntimeObjectLibraries 函数，决定是否异步加载运行时对象库
	virtual bool ShouldSyncLoadMissingGameplayCues() const override; // 重写 ShouldSyncLoadMissingGameplayCues 函数，决定是否同步加载缺失的 GameplayCues
	virtual bool ShouldAsyncLoadMissingGameplayCues() const override; // 重写 ShouldAsyncLoadMissingGameplayCues 函数，决定是否异步加载缺失的 GameplayCues
	//~End of UGameplayCueManager interface // 注释，表示 UGameplayCueManager 接口重写结束

	static void DumpGameplayCues(const TArray<FString>& Args); // 静态成员函数，用于打印 GameplayCues 的调试信息，接受一个 FString 数组作为参数

	// When delay loading cues, this will load the cues that must be always loaded anyway // 注释，说明此函数用于在延迟加载时加载那些必须始终加载的 Cues
	void LoadAlwaysLoadedCues(); // 成员函数，加载必须始终加载的 Cues

	// Updates the bundles for the singular gameplay cue primary asset // 注释，说明此函数用于更新单一 GameplayCue 主资源的 Bundles
	void RefreshGameplayCuePrimaryAsset(); // 成员函数，刷新 GameplayCue 主资源

private:
	void OnGameplayTagLoaded(const FGameplayTag& Tag); // 私有成员函数，处理 GameplayTag 加载完成后的回调，接受一个 FGameplayTag 引用作为参数
	void HandlePostGarbageCollect(); // 私有成员函数，处理垃圾回收完成后的回调
	void ProcessLoadedTags(); // 私有成员函数，处理已加载的 Tags
	void ProcessTagToPreload(const FGameplayTag& Tag, UObject* OwningObject); // 私有成员函数，根据 Tag 预加载 Cue，接受一个 FGameplayTag 和一个 UObject 指针作为参数
	void OnPreloadCueComplete(FSoftObjectPath Path, TWeakObjectPtr<UObject> OwningObject, bool bAlwaysLoadedCue); // 私有成员函数，处理 Cue 预加载完成的回调，接受 FSoftObjectPath、TWeakObjectPtr<UObject> 和 bool 作为参数
	void RegisterPreloadedCue(UClass* LoadedGameplayCueClass, UObject* OwningObject); // 私有成员函数，注册预加载的 Cue，接受 UClass 和 UObject 指针作为参数
	void HandlePostLoadMap(UWorld* NewWorld); // 私有成员函数，处理地图加载完成后的回调，接受 UWorld 指针作为参数
	void UpdateDelayLoadDelegateListeners(); // 私有成员函数，更新延迟加载委托的监听器
	bool ShouldDelayLoadGameplayCues() const; // 私有成员函数，判断是否应该延迟加载 GameplayCues

private:
	struct FLoadedGameplayTagToProcessData // 私有内部结构体，用于存储需要处理的已加载 GameplayTag 数据
	{
		FGameplayTag Tag; // FGameplayTag 成员变量，存储 Tag
		TWeakObjectPtr<UObject> WeakOwner; // TWeakObjectPtr<UObject> 成员变量，存储弱引用的所有者对象

		FLoadedGameplayTagToProcessData() {} // 默认构造函数
		FLoadedGameplayTagToProcessData(const FGameplayTag& InTag, const TWeakObjectPtr<UObject>& InWeakOwner) : Tag(InTag), WeakOwner(InWeakOwner) {} // 带参数的构造函数，初始化 Tag 和 WeakOwner
	};

private:
	// Cues that were preloaded on the client due to being referenced by content // 注释，说明此成员是客户端上由于被内容引用而预加载的 Cues
	UPROPERTY(transient) // UPROPERTY 宏，标记为 transient，表示该属性不被序列化
	TSet<TObjectPtr<UClass>> PreloadedCues; // TSet<TObjectPtr<UClass>> 成员变量，存储预加载的 Cue 类
	TMap<FObjectKey, TSet<FObjectKey>> PreloadedCueReferencers; // TMap 成员变量，键为 FObjectKey (Cue类)，值为 TSet<FObjectKey> (引用该 Cue 的对象)，存储预加载 Cue 的引用者

	// Cues that were preloaded on the client and will always be loaded (code referenced or explicitly always loaded) // 注释，说明此成员是客户端上预加载且始终加载的 Cues（代码引用或显式标记为始终加载）
	UPROPERTY(transient) // UPROPERTY 宏，标记为 transient，表示该属性不被序列化
	TSet<TObjectPtr<UClass>> AlwaysLoadedCues; // TSet<TObjectPtr<UClass>> 成员变量，存储始终加载的 Cue 类

	TArray<FLoadedGameplayTagToProcessData> LoadedGameplayTagsToProcess; // TArray 成员变量，存储需要处理的已加载 GameplayTag 数据
	FCriticalSection LoadedGameplayTagsToProcessCS; // FCriticalSection 成员变量，用于同步对 LoadedGameplayTagsToProcess 的访问
	bool bProcessLoadedTagsAfterGC = false; // bool 成员变量，标记是否在垃圾回收后处理已加载的 Tags，初始化为 false
};